﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.Modeling;
using VsxFactory.Modeling.Strategies.Rules;

namespace VsxFactory.Modeling.Strategies
{
    internal class PathUtilities
    {
        /// <summary>
        /// Retourne l'élément correspondant au path à partir d'une source
        /// </summary>
        /// <param name="context">Strategy context</param>
        /// <param name="source">Source à partir de laquelle faire la recherche</param>
        /// <param name="path">Chemin cible</param>
        /// <returns>Item1 correspond à l'élément cible et Item2 à la propriété cible de cet élément</returns>
        /// <remarks>
        /// Path : Peut prendre plusieurs valeurs :
        /// - Blanc ou null : La cible correspond à la source
        /// - Il peut contenir .. pour naviguer vers le projet de la source
        /// Ex : xxxx.Prop1 
        /// </remarks>
        public static Tuple<GenerationSpec, DomainPropertyInfo> GetElement(IStrategyContext context, GenerationSpec source, string path)
        {
            if (string.IsNullOrWhiteSpace(path))
                return new Tuple<GenerationSpec, DomainPropertyInfo>(source, null);

            Tuple<GenerationSpec, DomainPropertyInfo> result = null;
            Queue<string> segments = new Queue<string>(path.Split('.'));
            while (segments.Count > 0 && source != null)
            {
                var name = segments.Dequeue();
                if (name == "$Project")
                {
                    var projectElement = source.ModelElement.Store.ElementDirectory.GetElement(source.ProjectElementGuid);
                    if (source == null)
                        break;
                    source = context.Strategy.CreateGenerationSpec(context, projectElement);
                }
                else
                {
                    var rel = source.ModelElement.GetDomainClass().AllDomainRolesPlayed.FirstOrDefault(r => r.Name == name);
                    if (rel != null)
                    {
                        var player = rel.GetLinkedElement(source.ModelElement);
                        source = context.Strategy.CreateGenerationSpec(context, player);
                    }
                    else
                    {
                        var prop = source.ModelElement.GetDomainClass().AllDomainProperties.FirstOrDefault();
                        if (prop != null)
                            result = new Tuple<GenerationSpec, DomainPropertyInfo>(source, prop);
                        break;
                    }
                }
            }
            if (segments.Count != 0 || source == null)
                return null;

            return result ?? new Tuple<GenerationSpec, DomainPropertyInfo>(source, null);
        }
    }

}
